package com.zzyang.aop.demo.rpc.consumer;


import com.zzyang.aop.demo.rpc.anno.MyReference;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

/**
 * 注入标记 {@link MyReference} 注解代理对象
 *
 * @author zhuoziyang
 * @date 2021/5/19 22:13
 */
@Component
public class MyReferenceAnnotationBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
            @Override
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                MyReference myReference = field.getAnnotation(MyReference.class);
                Object proxyInstance = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                        new Class[]{field.getType()},
                        new MyReferenceInvocationHandler(myReference.url()));
                ReflectionUtils.makeAccessible(field);
                ReflectionUtils.setField(field, bean, proxyInstance);
            }
        }, new ReflectionUtils.FieldFilter() {
            @Override
            public boolean matches(Field field) {
                return field.isAnnotationPresent(MyReference.class) && field.getType().isInterface();
            }
        });
        return bean;
    }

}
